package com.eatme.web.sys.workflow.activiti.controller;

import com.eatme.web.common.QueryCondition;
import com.eatme.web.common.vo.AppResponse;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.util.*;

@RestController
@RequestMapping("/process/instance/history/")
public class ActivitiHistoryController {


    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private HistoryService historyService;

    //用户历史任务
   @PostMapping(value = "/userList")
    public AppResponse InstancesByUser(@RequestBody QueryCondition<Map<String,Object>> queryCondition, Principal principal) {
        Integer pageSize = queryCondition.getPage().getPageSize();
        Integer pageIndex = queryCondition.getPage().getPageIndex();
        List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
                .orderByHistoricTaskInstanceEndTime().asc().taskAssignee(principal.getName()).listPage(pageIndex,pageSize);
        List<Map<String, Object>> arrayList = new ArrayList<>();
        for (HistoricTaskInstance hti : historicTaskInstances) {
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("id", hti.getId());
            hashMap.put("startTime", hti.getStartTime());
            hashMap.put("endTime", hti.getEndTime());
            hashMap.put("description", hti.getDescription());
            hashMap.put("deleteReason", hti.getDeleteReason());
            arrayList.add(hashMap);
        }
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("total",historyService.createHistoricTaskInstanceQuery()
                .orderByHistoricTaskInstanceEndTime().asc().taskAssignee(principal.getName()).count());
        if (!historicTaskInstances.isEmpty()){
            resultMap.put("list",arrayList);
        }
        return AppResponse.ok().data(resultMap);
    }

    //任务实例历史
    @PostMapping(value = "/list")
    public AppResponse listByProcessInstanceId(@RequestBody QueryCondition<Map<String,Object>> queryCondition) {
        String processInstanceId = (String) queryCondition.getCondition().get("processInstanceId");
        Integer pageSize = queryCondition.getPage().getPageSize();
        Integer pageIndex = queryCondition.getPage().getPageIndex();
        //--------------------------------------------另一种写法-------------------------
        List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery().
                orderByHistoricTaskInstanceEndTime().asc().processInstanceId(processInstanceId).listPage(pageIndex,pageSize);
        List<Map<String, Object>> arrayList = new ArrayList<>();
        for (HistoricTaskInstance hti : historicTaskInstances) {
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("id", hti.getId());
            hashMap.put("startTime", hti.getStartTime());
            hashMap.put("endTime", hti.getEndTime());
            hashMap.put("description", hti.getDescription());
            hashMap.put("deleteReason", hti.getDeleteReason());
            arrayList.add(hashMap);
        }
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("total",historyService.createHistoricTaskInstanceQuery()
                .orderByHistoricTaskInstanceEndTime().asc().count());
        if (!historicTaskInstances.isEmpty()){
            resultMap.put("list",arrayList);
        }
        return AppResponse.ok().data(resultMap);
    }

    //流程图高亮
    @GetMapping("/highlight/{id}")
    public AppResponse gethighLine(@PathVariable(value = "id") String processInstanceId, Principal principal) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        //获取bpmnModel对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
        //因为我们这里只定义了一个Process 所以获取集合中的第一个即可
        Process process = bpmnModel.getProcesses().get(0);
        //获取所有的FlowElement信息
        Collection<FlowElement> flowElements = process.getFlowElements();
        Map<String, String> map = new HashMap<>();
        for (FlowElement flowElement : flowElements) {
            //判断是否是连线
            if (flowElement instanceof SequenceFlow) {
                SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
                String ref = sequenceFlow.getSourceRef();
                String targetRef = sequenceFlow.getTargetRef();
                map.put(ref + targetRef, sequenceFlow.getId());
            }
        }
        //获取流程实例 历史节点(全部)
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
        //各个历史节点   两两组合 key
        Set<String> keyList = new HashSet<>();
        for (HistoricActivityInstance i : list) {
            for (HistoricActivityInstance j : list) {
                if (i != j) {
                    keyList.add(i.getActivityId() + j.getActivityId());
                }
            }
        }
        //高亮连线ID
        Set<String> highLine = new HashSet<>();
        keyList.forEach(s -> highLine.add(map.get(s)));
        //获取流程实例 历史节点（已完成）
        List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).finished().list();
        //高亮节点ID
        Set<String> highPoint = new HashSet<>();
        listFinished.forEach(s -> highPoint.add(s.getActivityId()));

        //获取流程实例 历史节点（待办节点）
        List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).unfinished().list();
        //需要移除的高亮连线
        Set<String> set = new HashSet<>();
        //待办高亮节点
        Set<String> waitingToDo = new HashSet<>();
        listUnFinished.forEach(s -> {
            waitingToDo.add(s.getActivityId());
            for (FlowElement flowElement : flowElements) {
                //判断是否是 用户节点
                if (flowElement instanceof UserTask) {
                    UserTask userTask = (UserTask) flowElement;

                    if (userTask.getId().equals(s.getActivityId())) {
                        List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
                        //因为 高亮连线查询的是所有节点  两两组合 把待办 之后  往外发出的连线 也包含进去了  所以要把高亮待办节点 之后 即出的连线去掉
                        if (outgoingFlows != null && outgoingFlows.size() > 0) {
                            outgoingFlows.forEach(a -> {
                                if (a.getSourceRef().equals(s.getActivityId())) {
                                    set.add(a.getId());
                                }
                            });
                        }
                    }
                }
            }
        });
        highLine.removeAll(set);
        //获取当前用户
        //User sysUser = getSysUser();
        Set<String> iDo = new HashSet<>(); //存放 高亮 我的办理节点
        List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery().taskAssignee(principal.getName()).finished().processInstanceId(processInstanceId).list();
        taskInstanceList.forEach(a -> iDo.add(a.getTaskDefinitionKey()));
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("highlightElement", highPoint);
        resultMap.put("highlightConnection", highLine);
        resultMap.put("waitingToDoElement", waitingToDo);
        resultMap.put("iDoElement", iDo);
        resultMap.put("id",historicProcessInstance.getDeploymentId());
        return AppResponse.ok().data(resultMap);
    }


}
